/**
 * 数据验证工具
 * 提供API请求和响应数据的验证功能
 */

import { z } from 'zod';

// 定义API错误响应接口
export interface ApiErrorResponse {
  success: false;
  message: string;
  error: {
    type: string;
    code?: string;
    details?: any;
  }
  statusCode: number;
}

// 定义API成功响应接口
export interface ApiSuccessResponse<T = any> {
  success: true;
  message?: string;
  data?: T;
}

/**
 * 通用API响应验证器
 * @param schema 验证模式
 * @returns 验证后的数据
 */
export function validateApiResponse<T>(
  response: unknown, 
  schema: z.ZodType<T>
): T {
  // 首先验证是否是标准API响应格式
  const apiResponseSchema = z.object({
    success: z.boolean(),
    message: z.string().optional(),
    data: z.unknown().optional(),
    error: z.object({
      type: z.string(),
      code: z.string().optional(),
      details: z.unknown().optional(),
    }).optional(),
    statusCode: z.number().optional(),
  });

  // 验证API响应结构
  const validatedResponse = apiResponseSchema.parse(response);

  // 检查是否为错误响应
  if (!validatedResponse.success) {
    throw new Error(
      validatedResponse.message || 
      (validatedResponse.error && `错误类型: ${validatedResponse.error.type}`) || 
      '请求失败'
    );
  }

  // 验证数据部分
  if (validatedResponse.data !== undefined) {
    return schema.parse(validatedResponse.data);
  }

  // 如果没有data字段，则验证整个响应（去除success字段）
  const { success, ...rest } = validatedResponse;
  return schema.parse(rest);
}

/**
 * 异步验证API响应，包含错误处理
 */
export async function safeValidateApiResponse<T>(
  responsePromise: Promise<unknown>,
  schema: z.ZodType<T>
): Promise<T> {
  try {
    const response = await responsePromise;
    return validateApiResponse(response, schema);
  } catch (error) {
    if (error instanceof z.ZodError) {
      console.error('API响应数据验证失败:', error.errors);
      throw new Error(`API响应格式不符合预期: ${error.errors[0]?.message || '未知错误'}`);
    }
    throw error;
  }
}

/**
 * 验证请求数据
 */
export function validateRequestData<T>(
  data: unknown, 
  schema: z.ZodType<T>
): T {
  try {
    return schema.parse(data);
  } catch (error) {
    if (error instanceof z.ZodError) {
      console.error('请求数据验证失败:', error.errors);
      throw new Error(`请求数据验证失败: ${error.errors[0]?.message || '未知错误'}`);
    }
    throw error;
  }
}

/**
 * 常用的验证模式
 */
export const ValidationSchemas = {
  id: z.string().min(1, 'ID不能为空'),
  email: z.string().email('无效的邮箱地址'),
  password: z.string().min(8, '密码至少需要8个字符'),
  username: z.string().min(3, '用户名至少需要3个字符').max(50, '用户名不能超过50个字符'),
  date: z.string().refine(value => !isNaN(Date.parse(value)), {
    message: '无效的日期格式',
  }),
  url: z.string().url('无效的URL'),
  positiveNumber: z.number().positive('必须是正数'),
  nonNegativeNumber: z.number().nonnegative('不能是负数'),
  boolean: z.boolean(),
  array: z.array(z.unknown()),
  nonEmptyArray: z.array(z.unknown()).min(1, '数组不能为空'),
  nonEmptyString: z.string().min(1, '字符串不能为空'),
  trimmedString: z.string().trim().min(1, '字符串不能为空白'),
  
  // 任务状态
  taskStatus: z.enum(['TODO', 'IN_PROGRESS', 'REVIEW', 'DONE']),
  
  // 任务优先级
  taskPriority: z.enum(['LOW', 'MEDIUM', 'HIGH', 'URGENT']),
};

/**
 * 用户角色验证
 */
export const UserRoleSchema = z.enum(['USER', 'ADMIN']);

/**
 * 项目成员角色验证
 */
export const ProjectRoleSchema = z.enum(['OWNER', 'ADMIN', 'MEMBER', 'GUEST']);

/**
 * 用户验证模式
 */
export const UserSchema = z.object({
  id: ValidationSchemas.id,
  name: z.string().nullable().optional(),
  email: ValidationSchemas.email.nullable().optional(),
  image: z.string().nullable().optional(),
  createdAt: z.string().optional(),
  updatedAt: z.string().optional(),
});

/**
 * 任务验证模式
 */
export const TaskSchema = z.object({
  id: ValidationSchemas.id,
  title: ValidationSchemas.nonEmptyString,
  description: z.string().nullable().optional(),
  status: ValidationSchemas.taskStatus,
  priority: ValidationSchemas.taskPriority,
  dueDate: z.string().nullable().optional(),
  assigneeId: ValidationSchemas.id.nullable().optional(),
  projectId: ValidationSchemas.id,
  createdAt: z.string().optional(),
  updatedAt: z.string().optional(),
  // 可以根据需要添加其他字段
});

/**
 * 项目验证模式
 */
export const ProjectSchema = z.object({
  id: ValidationSchemas.id,
  name: ValidationSchemas.nonEmptyString,
  description: z.string().nullable().optional(),
  createdAt: z.string().optional(),
  updatedAt: z.string().optional(),
  // 可以根据需要添加其他字段
});

/**
 * 将验证模式转换为部分验证模式（用于更新操作）
 */
export function partialSchema<T extends z.ZodRawShape>(schema: z.ZodObject<T>) {
  return schema.partial();
}

/**
 * 将验证模式应用于数组
 */
export function arraySchema<T>(schema: z.ZodType<T>) {
  return z.array(schema);
} 